package com.silence.gmall.component.impl;

import com.alibaba.fastjson2.JSON;
import com.silence.gmall.component.CatchOpsComponent;
import com.silence.gmall.constant.ProductRedisStringConstant;
import com.silence.gmall.enums.CommonCode;
import com.silence.gmall.exception.ServiceException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Type;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @Author silence
 * @Date 2025-09-30 14:08
 * @Email 792245022@qq.com
 * @Version 1.0
 * @Description 缓存操作组件实现类
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class CatchOpsComponentImpl implements CatchOpsComponent {

    /**
     * Redis模板
     */
    private final StringRedisTemplate stringRedisTemplate;

    /**
     * 获取缓存数据
     *
     * @param key  缓存key
     * @param type 返回值类型
     * @param <T>  返回值类型
     * @return 缓存数据
     */
    @Override
    public <T> Optional<T> getCatchData(String key, Type type) {
        // 获取缓存数据
        String json = getCatchData(key);

        if (StringUtils.isBlank(json)) {
            return Optional.empty();
        }

        // 解析缓存数据
        return Optional.ofNullable(JSON.parseObject(json, type));
    }

    /**
     * 获取缓存数据
     *
     * @param key   缓存key
     * @param clazz 返回值类型
     * @param <T>   返回值类型
     * @return 缓存数据
     */
    @Override
    public <T> Optional<T> getCatchData(String key, Class<T> clazz) {
        // 获取缓存数据
        String json = getCatchData(key);

        if (StringUtils.isBlank(json)) {
            return Optional.empty();
        }

        // 解析缓存数据
        return Optional.ofNullable(JSON.parseObject(json, clazz));
    }

    /**
     * 获取缓存数据
     *
     * @param key 缓存key
     * @return 缓存数据
     */
    private String getCatchData(String key) {
        // 获取缓存数据
        String json = stringRedisTemplate.opsForValue().get(key);

        if (StringUtils.isBlank(json)) {
            return "";
        }

        if (Objects.equals(ProductRedisStringConstant.TEMP_REDIS_DATA, json)) {
            throw new ServiceException(CommonCode.DATA_NOT_FOUND);
        }

        return json;
    }

    /**
     * 保存缓存数据
     *
     * @param key     缓存key
     * @param data    缓存数据
     * @param timeout 缓存过期时间
     * @param unit    时间单位
     */
    @Override
    public void saveData(String key, Object data, long timeout, TimeUnit unit) {
        String jsonData = Objects.nonNull(data) ? JSON.toJSONString(data) : ProductRedisStringConstant.TEMP_REDIS_DATA;

        if (Objects.isNull(data)) {
            log.info("缓存数据为空，key:{}", key);
            stringRedisTemplate.opsForValue().set(key, jsonData, 1L, TimeUnit.HOURS);
            return;
        }

        stringRedisTemplate.opsForValue().set(key, jsonData, timeout, unit);
    }
}
